package multi_thread.advanced;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Cheng Jun
 * Description: 演示 原子类的 ABA 问题
 * @version 1.0
 * @date 2021/9/25 0:43
 * @see AtomicStampedReferenceExample
 */
public class AtomicBooleanExample {

    private static AtomicBoolean OPEN_OR_CLOSE = new AtomicBoolean(false);

    public static void main(String[] args) throws InterruptedException {
        boolean expect = OPEN_OR_CLOSE.get();
        boolean update = true;

        Thread zhangsan = new Thread(() -> {
            boolean isOpen = OPEN_OR_CLOSE.compareAndSet(expect, update);
            System.out.println(Thread.currentThread().getName() + "开柜门：" + isOpen);
            // 省略 偷试题的操作
            boolean isClose = OPEN_OR_CLOSE.compareAndSet(OPEN_OR_CLOSE.get(), expect);
            System.out.println(Thread.currentThread().getName() + "关柜门：" + isClose);
            System.out.println(Thread.currentThread().getName() + "偷题是否成功" + (isOpen && isClose));
        }, "zhangsan");

        Thread lisi = new Thread(() -> {
            try {
                // 张三使手段，确保自己先执行完，真实场景可能用其它的手段
                zhangsan.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "打开之前门状态为：" + OPEN_OR_CLOSE.get());
            boolean isOpen = OPEN_OR_CLOSE.compareAndSet(expect, update);
            System.out.println(Thread.currentThread().getName() + "打开之后门状态为：" + OPEN_OR_CLOSE.get() + ", "
                    + Thread.currentThread().getName() + "开柜门是否成功：" + isOpen);
        }, "lisi");

        // 当然这个地方最好用 发令枪做，同时起跑
        zhangsan.start();
        lisi.start();
    }
}
